package com.wyiot.pet.service;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wyiot.pet.mapper.UserMapper;
import com.wyiot.pet.model.dto.LoginDTO;
import com.wyiot.pet.model.entity.UserDO;
import com.wyiot.pet.model.vo.UserVO;
import com.wyiot.core.security.UserToken;
import com.wyiot.core.utils.Md5Util;
import com.wyiot.core.exception.ValidateException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 登入Service
 * @author yly
 * @since  2022年03月28日
 */
@Service
public class LoginService {
    @Resource
    UserMapper userMapper;
    @Resource
    UserService userService;

    /**账号默认锁定时长*/
    private final static int DEFAULT_LOCK_TIME = 5;

    /**用户输入错误次数的计数器，简单替代缓存*/
    private final Map<Long, Integer> errCountMap = new HashMap<>();



    /**
     * 封装login返回结果
     *
     * @param user 登录用户信息
     * @return 用户登录信息
     */
    public UserToken generateUserToken(UserVO user) {
        // 构建登录成功返回信息
        UserToken userToken = UserToken.builder()
                .tokenName(StpUtil.getTokenName())
                .tokenValue(StpUtil.getTokenValue())
                .userId(user.getUserId())
                .userName(user.getUserName())
                .userPhone(user.getUserPhone())
                .userCode(user.getUserCode())
                .build();
        // 更新用户最后登录时间
        userService.update(Wrappers.lambdaUpdate(UserDO.class)
                .set(UserDO::getLastLoginTime, new Date())
                .eq(UserDO::getUserId, user.getUserId()));
        return userToken;
    }

    public UserVO checkLoginUser(LoginDTO loginDTO) {
        UserVO user = userMapper.selectUserByCode(loginDTO.getUserCode());
        if (Objects.isNull(user)) {
            throw ValidateException.of("账号不存在");
        }
        if (!user.getUserStatus()) {
            throw ValidateException.of("账号已禁用");
        }
        if (!user.getUserPassword().equals(Md5Util.code(loginDTO.getUserPassword()))) {
            /*记录错误次数，或锁定账户*/
            Integer errCount = errCountMap.get(user.getUserId());
            errCount = errCount == null ? 1 : errCount + 1;//三位运算
            if (errCount > 3) {
                userMapper.updateLocktimeById(new Date(), user.getUserId());//锁定
                errCountMap.remove(user.getUserId());//清除
            } else {
                errCountMap.put(user.getUserId(), errCount);
            }
            throw ValidateException.of("账号或密码错误");
        } else if (user.getUserLockTime() != null && DEFAULT_LOCK_TIME * 60000 > (System.currentTimeMillis() - user.getUserLockTime().getTime())) {
            throw ValidateException.of("账号锁定5分钟，请稍后再试");
        } else if (user.getUserLockTime() != null) {
            userMapper.updateLocktimeById(null, user.getUserId());//解锁
        }
        return user;
    }
}